﻿using System;
using System.Drawing;
using System.Threading;
using LumiSoft.Net;
using LumiSoft.Net.Mime.vCard;
using Zuehlke.Blueprint.Quickstart.Architecture.Domain.Services.Interfaces;

namespace Zuehlke.Blueprint.Quickstart.Architecture.Domain.Services
{
    /// <summary>
    /// See <see cref="ICustomerPersistencyService"/>.
    /// </summary>
    public class CustomerPersistencyService : ICustomerPersistencyService
    {
        #region Private Members

        private static readonly Random Random = new Random();

        #endregion

        #region ICustomerPersistencyService Members

        /// <summary>
        /// See <see cref="ICustomerPersistencyService.GetCustomersCount"/>.
        /// </summary>
        public int GetCustomersCount()
        {
            var count = new VCardProvider().CardCount;
            return count;
        }

        /// <summary>
        /// See <see cref="ICustomerPersistencyService.LoadCustomer"/>.
        /// </summary>
        public IReadonlyCustomer LoadCustomer(int index)
        {
            if (index >= GetCustomersCount())
            {
                throw new IndexOutOfRangeException(string.Format("No customer available for index {0}", index));
            }

            // Simulate latency
            var sleepTime = Random.Next(0, 20);
            Thread.Sleep(sleepTime);

            using (var vCardProvider = new VCardProvider())
            {
                var vCard = vCardProvider.GetCardAt(index);
                var phoneWork = GetPhone(vCard.PhoneNumbers, PhoneNumberType_enum.Voice); // The work phone is NOT stored as work type within the Zuehlke vCards
                var mailAddressWork = GetMail(vCard.EmailAddresses, (EmailAddressType_enum)3); // The direct call number is stored as type 3 within the Zuehlke vCards
                var vCardCustomer = new ReadonlyCustomer(vCard.Name.FirstName, vCard.Name.LastName, vCard.Photo, vCard.Title, phoneWork, mailAddressWork);
                return vCardCustomer;
            }
        }

        #endregion

        #region Private Helpers

        private static string GetPhone(PhoneNumberCollection phoneNumberCollection, PhoneNumberType_enum phoneType)
        {
            foreach(var item in phoneNumberCollection)
            {
                var phoneNumber = item as PhoneNumber;
                if(phoneNumber == null)
                {
                    continue;
                }

                if(phoneNumber.NumberType == phoneType)
                {
                    return phoneNumber.Number;
                }
            }

            return null;
        }

        private static string GetMail(EmailAddressCollection emailAddressCollection, EmailAddressType_enum mailType)
        {
            foreach (var item in emailAddressCollection)
            {
                var emailAddress = item as EmailAddress;
                if (emailAddress == null)
                {
                    continue;
                }

                if (emailAddress.EmailType == mailType)
                {
                    return emailAddress.Email;
                }
            }

            return null;
        }

        #endregion

        #region Nested Class

        private class ReadonlyCustomer : IReadonlyCustomer
        {
            #region Constructor

            public ReadonlyCustomer(string firstName, string lastName, Image photo, string title, string phoneWork, string mailAddressWork)
            {
                Id = Guid.NewGuid();
                FirstName = firstName;
                LastName = lastName;
                Photo = photo;
                Title = title;
                PhoneWork = phoneWork;
                MailAddressWork = mailAddressWork;
            }

            #endregion

            #region IReadonlyCustomer Members

            public Guid Id { get; private set; }
            public string FirstName { get; private set; }
            public string LastName { get; private set; }
            public Image Photo { get; private set; }
            public string Title { get; private set; }
            public string PhoneWork { get; private set; }
            public string MailAddressWork { get; private set; }

            #endregion
        }

        #endregion
    }
}
